package main

import (
	"fmt"
	"strconv"
	"unicode"
)

// Token 结构体表示一个词法单元
type Token struct {
	Type  int    // 词法单元类型
	Value string // 词法单元值
	Len   int    // 词法单元长度
	Next  *Token // 指向下一个Token的指针
}

const (
	TK_NUM   = 1 // 数字
	TK_PUNCT = 2 // 标点符号
	TK_EOF   = 3 // 文件结束符
)

// newToken 创建一个新的Token
func newToken(tokenType int, start, end *string) *Token {
	value := ""
	if start != nil && end != nil {
		value = *start
	}
	return &Token{
		Type:  tokenType,
		Value: value,
		Len:   len(value),
		Next:  nil,
	}
}

// tokenize 将输入字符串解析成Token链表
func tokenize(P string) *Token {
	Head := &Token{} // 头节点
	Cur := Head      // 当前节点指针

	for _, r := range P {
		if unicode.IsSpace(r) {
			continue
		}

		if unicode.IsDigit(r) {
			start := P[Cur.Len:]
			num, _ := strconv.ParseUint(start, 10, 64)
			end := P[Cur.Len+len(strconv.FormatUint(num, 10)):]
			fmt.Println(start, end)
			fmt.Println(num)
			// Cur.Next = newToken(TK_NUM, start, end)
			Cur = Cur.Next
			Cur.Value = strconv.FormatUint(num, 10)
			Cur.Len = len(Cur.Value)
			continue
		}

		/* if r == '+' || r == '-' {
			start := P[Cur.Len:]
			end := P[Cur.Len+1:]
			Cur.Next = newToken(TK_PUNCT, start, end)
			Cur = Cur.Next
			Cur.Value = string(r)
			Cur.Len = 1
			continue
		} */

		fmt.Printf("invalid token: %c\n", r)
		return nil
	}

	// 解析结束，增加一个EOF，表示终止符。
	Cur.Next = newToken(TK_EOF, &P, &P)
	return Head.Next
}

func main() {
	input := "  123 + 456 - 789  "
	tokens := tokenize(input)

	// 打印解析出的Token
	for token := tokens; token != nil; token = token.Next {
		fmt.Printf("Type: %d, Value: %s, Len: %d\n", token.Type, token.Value, token.Len)
	}
}
